package vn.edu.hut.soict.translate.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import vn.edu.hut.soict.translate.database.TranslatorDatabase;

public class SemanticDistance {
	// Natural logarithm of the number of Google indexed pages
	private static final int LOG_M = 36;

	private static final String searchString = "http://www.google.com.vn/search?q=";

	private static TranslatorDatabase database;

	static {
		database = new TranslatorDatabase();
		database.connect();
	}

	private static int numberOfResults(String string) {
		HttpURLConnection connection = null;
		BufferedReader reader = null;
		try {
			URL url = new URL(searchString + string.replace(" ", "+"));
			connection = (HttpURLConnection) url.openConnection();
			connection.addRequestProperty("User-Agent", "Mozilla/4.76");
			connection.connect();

			// Get charset
			String contentType = connection.getHeaderField("Content-Type");
			String charset = null;
			for (String param : contentType.split(";")) {
				param = param.trim();
				if (param.startsWith("charset=")) {
					charset = param.split("=", 2)[1];
					break;
				}
			}

			reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), charset));
		}
		catch (MalformedURLException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}

		// Find the number of results
		boolean found = false;
		String line;
		String num = null;
		try {
			while (!found && ((line = reader.readLine()) != null)) {
				int start = line.indexOf("</b> trong khoa&#777;ng <b>");
				int end = line.indexOf("</b> cho <b>");
				if (start > -1) {
					num = line.substring(start + 27, end);
					num = num.replaceAll(",.", "");
					found = true;
				}
			}
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		connection.disconnect();

		if (num == null) {
			return 1;
		}
		return Integer.parseInt(num);
	}

	private static double calculateByCorpus(String word1, String word2) {
		return database.getSimilarity(word1, word2);
	}

	/*
	 * Normalized Google Distance.
	 */
	private static double calculateByNGD(String word1, String word2) {
		int fx = database.getGoogleResultCount(word1);
		if (fx < 0) {
			fx = numberOfResults("\"" + word1 + "\"");
			database.insertRowToGoogleResultCount(word1, fx);
		}

		int fy = database.getGoogleResultCount(word2);
		if (fy < 0) {
			fy = numberOfResults("\"" + word2 + "\"");
			database.insertRowToGoogleResultCount(word2, fy);
		}

		int fxy = numberOfResults("\"" + word1 + "\" \"" + word2 + "\"");

		int min, max;
		if (fx > fy) {
			min = fy;
			max = fx;
		}
		else {
			min = fx;
			max = fy;
		}

		double similarity = (Math.log(max) - Math.log(fxy)) / (LOG_M - Math.log(min));
		database.insertRowToSimilarity(word1, word2, similarity);

		System.out.printf("NGD between %s and %s is: %f\n", word1, word2, similarity);

		return similarity;
	}

	public static double calculate(String word1, String word2) {
		double distance = SemanticDistance.calculateByCorpus(word1, word2);
		if (distance >= 0) {
			return distance;
		}
		else {
			return SemanticDistance.calculateByNGD(word1, word2);
		}
		// return 0.1;
	}
}
